package com.ruoyi.wecom.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.business.domain.wecom.TbWecomExternalContactFollowUser;
import com.ruoyi.business.service.wecom.ITbWecomCallbackMsgInfoService;
import com.ruoyi.business.service.wecom.ITbWecomExternalContactFollowUserService;
import com.ruoyi.business.service.wecom.ITbWecomMsgArchiveService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.wecom.*;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;


@RestController
@RequestMapping("/wechat/cp")
@Slf4j
public class WecomCallBackController {

    @Resource
    private WxCpService wxCpService;

    @Resource
    private ITbWecomCallbackMsgInfoService tbWecomCallbackMsgInfoService;

    @Resource
    private ITbWecomMsgArchiveService tbWecomMsgArchiveService;

    @Resource
    private ITbWecomExternalContactFollowUserService tbWecomExternalContactFollowUserService;

    /**
     * 企业微信回调验证（GET请求）
     */
    @GetMapping
    public String callbackVerify(
        @RequestParam("msg_signature") String signature,
        @RequestParam("timestamp") String timestamp,
        @RequestParam("nonce") String nonce,
        @RequestParam("echostr") String echostr) {
        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        try {
            if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) {
                return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr);
            }
        } catch (Exception e) {
            log.error("验证URL失败", e);
        }

        return "非法请求";
    }

    /**
     * 接收客户联系事件（POST请求）
     */
    @PostMapping
    public String handleCallback(
        @RequestParam("msg_signature") String signature,
        @RequestParam("timestamp") String timestamp,
        @RequestParam("nonce") String nonce,
        @RequestBody String postData) {
        try {
            // 解密消息
            WxCpXmlMessage message = WxCpXmlMessage.fromEncryptedXml(
                postData, wxCpService.getWxCpConfigStorage(), timestamp, nonce, signature);
            log.info("企微回调数据message：{}", message);
            // 处理事件类型
            WecomMsgCallBackEventEnum enumByType = WecomMsgCallBackEventEnum.getEnumByType(message.getEvent());
            switch (enumByType) {
                case MSG_AUDIT_NOTIFY:  // 会话存档消息回调
                    log.info("会话存档消息回调");
                    tbWecomMsgArchiveService.handleMsgAuditNotifyEvent(message);
                    break;
                case CHANGE_EXTERNAL_CONTACT:  // 客户联系事件
                    handleExternalContactEvent(message);
                    break;
                case CHANGE_EXTERNAL_CHAT:     // 客户群事件
                    handleExternalChatEvent(message);
                    break;
                case CHANGE_EXTERNAL_TAG:     // 群标签
                    handleExternalTagEvent(message);
                    break;
                case SUBSCRIBE:       //关注
                    handleSubscribeEvent(message);
                    break;
                case UNSUBSCRIBE:     //取消关注
                    handleUnSubscribeEvent(message);
                    break;
                case ENTER_AGENT:     //进入应用
                    log.info("本事件在成员进入企业微信的应用时触发");
                    break;
                case BATCH_JOB_RESULT:     //异步任务完成事件推送
                    log.info("本事件是成员在使用异步任务接口时，用于接收任务执行完毕的结果通知");
                    break;
                case LOCATION:     //上报地址位置
                    log.info("成员同意上报地理位置后，每次在进入应用会话时都会上报一次地理位置");
                    break;
                default:
                    // 忽略其他事件
                    log.info("忽略其他事件");
                    break;
            }
            return "success";
        } catch (Exception e) {
            throw new RuntimeException("处理回调失败", e);
        }
    }


    private void handleSubscribeEvent(WxCpXmlMessage message) {
        // 关注事件
        log.info("成员已经加入企业，管理员添加成员到应用可见范围时 回调");
        WxCpUser wxCpUser = null;
        try {
            wxCpUser = wxCpService.getUserService().getById(message.getFromUserName());
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        // 查询是否存在，不存在就新增
        TbWecomExternalContactFollowUser tbWecomExternalContactFollowUser = tbWecomExternalContactFollowUserService.getOne(Wrappers.lambdaQuery(TbWecomExternalContactFollowUser.class)
            .eq(TbWecomExternalContactFollowUser::getUserId, message.getFromUserName())
            .eq(TbWecomExternalContactFollowUser::getAgentId, message.getEvent())
            .orderByDesc(TbWecomExternalContactFollowUser::getCreateTime)
            .last(Constants.MYBATIS_PLUSH_LIMIT_ONE)
        );
        if (ObjectUtil.isEmpty(tbWecomExternalContactFollowUser)) {
            // 添加到 客服里
            TbWecomExternalContactFollowUser followUser = new TbWecomExternalContactFollowUser();
            followUser.setId(IdWorker.getId());
            followUser.setAgentId(message.getAgentId());
            followUser.setUserId(message.getFromUserName());
            followUser.setStatus("subscribe");
            followUser.setUserName(wxCpUser.getName());
            tbWecomExternalContactFollowUserService.save(followUser);
        } else {
            tbWecomExternalContactFollowUser.setStatus("subscribe");
            tbWecomExternalContactFollowUser.setUserName(wxCpUser.getName());
            tbWecomExternalContactFollowUserService.updateById(tbWecomExternalContactFollowUser);
        }
    }

    private void handleUnSubscribeEvent(WxCpXmlMessage message) {
        // 取消关注
        log.info("取消关注");
        // 查询是否存在，不存在就新增
        TbWecomExternalContactFollowUser tbWecomExternalContactFollowUser = tbWecomExternalContactFollowUserService.getOne(Wrappers.lambdaQuery(TbWecomExternalContactFollowUser.class)
            .eq(TbWecomExternalContactFollowUser::getUserId, message.getFromUserName())
            .eq(TbWecomExternalContactFollowUser::getAgentId, message.getEvent())
            .orderByDesc(TbWecomExternalContactFollowUser::getCreateTime)
            .last(Constants.MYBATIS_PLUSH_LIMIT_ONE)
        );
        if (ObjectUtil.isEmpty(tbWecomExternalContactFollowUser)) {
            // 添加到 客服里
            TbWecomExternalContactFollowUser followUser = new TbWecomExternalContactFollowUser();
            followUser.setId(IdWorker.getId());
            followUser.setAgentId(message.getAgentId());
            followUser.setUserId(message.getFromUserName());
            followUser.setStatus("unsubscribe");
            followUser.setUserName(message.getFromUserName());
            tbWecomExternalContactFollowUserService.save(followUser);
        } else {
            tbWecomExternalContactFollowUser.setStatus("unsubscribe");
            tbWecomExternalContactFollowUserService.updateById(tbWecomExternalContactFollowUser);
        }
    }

    /**
     * 处理客户变更事件（添加/删除/编辑客户）
     */
    private void handleExternalContactEvent(WxCpXmlMessage message) {
        String changeType = message.getChangeType(); // add_external_contact, edit_external_contact, del_external_contact
        String userId = message.getUserId();        // 企业员工UserID
        String externalUserId = message.getExternalUserId();
        WecomMsgCallBackExternalContactChangeTypeEnum enumByType = WecomMsgCallBackExternalContactChangeTypeEnum.getEnumByType(changeType);
        // 客户ExternalUserID
        switch (enumByType) {
            // 添加企业客户事件
            case ADD_EXTERNAL_CONTACT:
                // 新增客户逻辑
                log.info("员工:{} 添加了客户:{}", userId, externalUserId);
                tbWecomCallbackMsgInfoService.addExternalContactHandler(message);
                break;
            // 编辑企业客户事件
            case EDIT_EXTERNAL_CONTACT:
                log.info("配置了客户联系功能的成员修改外部联系人的备注、手机号或标签时，回调该事件");
                tbWecomCallbackMsgInfoService.editExternalContactHandler(message);
                break;
            // 外部联系人免验证添加成员事件
            case ADD_HALF_EXTERNAL_CONTACT:
                log.info("外部联系人免验证添加成员事件");
                // 外部联系人添加了配置了客户联系功能且开启了免验证的成员时（此时成员尚未确认添加对方为好友），回调该事件
                tbWecomCallbackMsgInfoService.addHalfExternalContact(message);
                break;
            // 删除企业客户事件
            case DEL_EXTERNAL_CONTACT:
                // 删除企业客户事件
                // 配置了客户联系功能的成员删除外部联系人时
                log.info("员工:{} 删除了客户:{}", userId, externalUserId);
                tbWecomCallbackMsgInfoService.delExternalContactHandler(message);
                break;
            // 删除跟进成员事件
            case DEL_FOLLOW_USER:
                // 删除跟进成员事件
                // 配置了客户联系功能的成员被外部联系人删除时
                log.info("删除跟进成员事件");
                tbWecomCallbackMsgInfoService.delFollowUser(message);
                break;
            // 客户接替失败事件
            case TRANSFER_FAIL:
                // 客户接替失败事件
                log.info("客户接替失败事件");
                tbWecomCallbackMsgInfoService.transferFail(message);
                break;
            // 客户同意会话存档回调
            case MSG_AUDIT_APPROVED:
                log.info("客户同意会话存档回调");
                break;
            default:
                // 其他变更类型
                log.info("客户联系其他变更类型");
                break;
        }
    }

    /**
     * 企业客户标签
     */
    private void handleExternalTagEvent(WxCpXmlMessage message) {
        String changeType = message.getChangeType();
        WecomMsgCallBackTagChangeTypeEnum enumByType = WecomMsgCallBackTagChangeTypeEnum.getEnumByType(changeType);
        switch (enumByType) {
            // 企业客户标签创建事件
            case TAG_CREATE:
                log.info("企业客户标签创建事件");
                // 企业客户标签创建事件
                tbWecomCallbackMsgInfoService.tagCreatEventHandler(message);
                break;
            case TAG_UPDATE:
                log.info("企业客户标签变更事件");
                // 企业客户标签变更事件
                tbWecomCallbackMsgInfoService.tagUpdateEventHandler(message);
                break;
            case TAG_DELETE:
                log.info("企业客户标签删除事件");
                // 企业客户标签删除事件
                tbWecomCallbackMsgInfoService.tagDeleteEventHandler(message);
                break;
            case TAG_SHUFFLE:
                log.info("企业客户标签重排事件");
                // 企业客户标签重排事件
                tbWecomCallbackMsgInfoService.tagShuffleEventHandler(message);
                break;
            default:
                log.info("标签与标签组其他变更类型");
                break;
        }


    }

    /**
     * 处理客户群事件（群创建/变更/解散）
     */
    private void handleExternalChatEvent(WxCpXmlMessage message) {
        String changeType = message.getChangeType();
        String chatId = message.getChatId();
        log.info("客户群id chatId:{}", chatId);
        log.info("changeType:{}", changeType);
        WecomMsgCallBackGroupChangeTypeEnum enumByType = WecomMsgCallBackGroupChangeTypeEnum.getEnumByType(changeType);
        // 具体业务逻辑...
        switch (enumByType) {
            // 创建群聊
            case GROUP_CREATE:
                // 创建群聊
                log.info("消息回调-->创建群聊");
                tbWecomCallbackMsgInfoService.groupCreatEventHandler(message);
                break;
            case GROUP_UPDATE:
                if (StringUtils.equals(message.getUpdateDetail(), WecomChatGroupUpdateTypeEnum.ADD_MEMBER.getCode())) {
                    // 成员入群
                    log.info("消息回调群变更事件-->成员入群");
                    tbWecomCallbackMsgInfoService.groupMemberAddEventHandler(message);
                }

                if (StringUtils.equals(message.getUpdateDetail(), WecomChatGroupUpdateTypeEnum.DEL_MEMBER.getCode())) {
                    // 成员退群
                    log.info("消息回调群变更事件 成员退群");
                    tbWecomCallbackMsgInfoService.groupMemberDelEventHandler(message);
                }

                if (StringUtils.equals(message.getUpdateDetail(), WecomChatGroupUpdateTypeEnum.CHANGE_OWNER.getCode())) {
                    // 群主变更
                    log.info("消息回调群变更事件 群主变更");
                    tbWecomCallbackMsgInfoService.groupChangeOwnerEventHandler(message);
                }

                if (StringUtils.equals(message.getUpdateDetail(), WecomChatGroupUpdateTypeEnum.CHANGE_NAME.getCode())) {
                    // 群名变更
                    log.info("消息回调群变更事件 群名变更");
                    tbWecomCallbackMsgInfoService.groupChangeNameEventHandler(message);
                }

                if (StringUtils.equals(message.getUpdateDetail(), WecomChatGroupUpdateTypeEnum.CHANGE_NOTICE.getCode())) {
                    // 群公告变更
                    log.info("消息回调群变更事件 群公告变更");
                    tbWecomCallbackMsgInfoService.groupChangeNoticeEventHandler(message);
                }
                break;
            case GROUP_DISMISS:
                // 客户群解散事件
                log.info("客户群解散事件");
                tbWecomCallbackMsgInfoService.groupDismissEventHandler(message);
                break;
            default:
                log.info("处理客户群事件 其他变更类型");
                break;
        }


    }

}
